/** @file         top_fsm.c
 *  @brief        二阶状态机的实现（顶层部分）
 *  @author       Schips
 *  @date         2021-01-22 19:03:20
 *  @version      v1.0
 *  @copyright    Copyright By Schips, All Rights Reserved
 */

#include <stdio.h>
#include "openfsm.h"
#include "sub_fsm.h"

typedef struct {
    int cnt;
} SM_DATA;

/*
 *  说明
 *
 *  关于修改状态机的状态，需要按照 如下的 函数类型声明与实现
 *
 *      其次，在状态函数的最后需要用 return 返回 ns(next state)
 *
 * */
/* ------------------- Functions -----------------------------*/
/* 状态机 函数指针 区域 */
void* top_step_init(void* this_fsm);
void* top_step_do_something(void* this_fsm);//计数
void* top_step_done(void* this_fsm);//计数完成
void* top_step_default(void* this_fsm);//错误过程


/* 状态定义(这里的顺序要求与 procedure_list[] 一致) */
enum procedure_id {
    top_state_init,
    top_state_do_something,
    top_state_done,
    top_state_default
};

/* 状态机调整列表 */
static Procedure procedure_list[] = {
    top_step_init,
    top_step_do_something,
    top_step_done,
    top_step_default
};

// 子状态 相关
static FSM sub_fsm = {0};
//static SM_DATA sub_data;

void* top_step_init(void* this_fsm)
{
    Procedure* procedure_list_for_sub_fsm = get_sub_procedure_list();
    SM_DATA *pd = get_data_entry(this_fsm);
    static SM_DATA sub_data_cnt;

    printf(">[%s]\n",__func__);

    // 状态处理
    set_next_state(this_fsm, top_state_do_something);

    // 数据处理
    if(pd)
        pd->cnt = 0;
    // 为 子状态机 设置 需要的 过程序列、参数
    set_procedures(&sub_fsm, procedure_list_for_sub_fsm);
    //set_data_entry(&sub_fsm, &sub_data);
    set_default_state(&sub_fsm, sub_state_init);
    set_data_entry(&sub_fsm, &sub_data_cnt);


    return NULL;
}

void* top_step_do_something(void* this_fsm)//计数
{
    state sub_fsm_cur_state;
    step_ret ret;

    printf(">[%s]\n",__func__);

    // 二阶状态机 调用
    if(is_curr_state(&sub_fsm, sub_state_done))
    {
        set_next_state(this_fsm, top_state_done);
    } else 
    {
        printf(" ├──Sub fsm : Before runing: %d\n", get_curr_state(&sub_fsm));

        sub_fsm_cur_state = run_state_machine_once(&sub_fsm);

        printf(" ├──Sub fsm : Ran :%d\n", sub_fsm_cur_state);
        printf(" └──Sub fsm : Next :%d\n", get_next_state(&sub_fsm));
        if(is_fsm_error(&sub_fsm))
        {
            printf("Error in sub\n");
            ret = (step_ret) get_step_retval(&sub_fsm);
            printf("Get err : %lld\n", ret);
            set_next_state(this_fsm, top_state_done);
        }
    }

    return NULL;
}

void* top_step_done(void* this_fsm)//计数完成
{
    printf(">[%s]\n",__func__);
    return NULL;
}

void* top_step_default(void* this_fsm) //默认
{
    set_next_state(this_fsm, top_state_done);
    return NULL;
}

int main(int argc, char *argv[])
{
    int i = 10;
    state cur_state;
    FSM top_fsm = {0};
    SM_DATA top_data={0};   

    set_procedures(&top_fsm, procedure_list);
    set_data_entry(&top_fsm, &top_data);
    set_default_state(&top_fsm, top_state_init);

    while(i--)
    {
        printf("=================\n");
        printf("Before runing: %d\n", get_curr_state(&top_fsm));

        cur_state = run_state_machine_once(&top_fsm);

        printf("Ran :%d\n", cur_state);
        printf("Next :%d\n", get_next_state(&top_fsm));

        // 停止条件
        if(is_curr_state(&top_fsm, top_state_done))
        {
            printf("Done\n");
            reset_state_machine(&top_fsm);
            break;
        }
    }

    return 0;
}

